<?php

namespace App\Http\Controllers\Api\SmallApp\Order;

use App\Http\Controllers\Common\ApiController;
use App\Models\Common\China;
use App\Models\Constant\OrderConstant;
use App\Models\Order\Ocr;
use App\Models\Order\Order;
use App\Models\Repair\RepairFactory;
use App\Models\Repair\RepairFactoryAdmin;
use App\Models\Setting\SysSetting;
use App\Models\User\ChengBao;
use App\Models\User\User;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;
use TencentCloud\Common\Credential;
use TencentCloud\Common\Profile\ClientProfile;
use TencentCloud\Common\Profile\HttpProfile;
use TencentCloud\Ocr\V20181119\Models\RecognizeTableOCRRequest;
use TencentCloud\Ocr\V20181119\OcrClient;

class ApplyController extends ApiController {


    public function isAllowApply(Request $request) {
        $token = $request->header('token');
        $id = checkJWT($token)['id'];
        $user = User::where(compact('id'))->first();
        if(empty($user))
            return responseFail('未找到有效用户');
        if(!$user->isAllowApply()){
            return responseFail('您的申请次数已达到上限，不允许再次申请服务');
        }else{
            return responseSuccess();
        }
    }

    public function uploadDingSun(Request $request) {
        $file = $request->file('file');
        if(empty($file) || !$file->isValid()){
            return responseFail('文件无效！');
        }
        $size =  $file->getSize();
        $ext = $file->getClientOriginalExtension();
        $module = $request->input('module','order');
        //检查目录
        $middlePath = "/$module/".date('Y-m-d');
        $absDir = Storage::disk('upload')->path($middlePath);
        //if(!is_dir($absDir)){mkdir($absDir,0777,true);}

        $fileName = time().uniqid().".$ext";

        //$imgIsCutSize = $request->input('imgIsCutSize',env('IMG_IS_CUT_SIZE',1024*1024*6));//压缩阈值
        //if( in_array($ext, ['jpg','png','jpeg','bmp']) && $size>$imgIsCutSize){
        $imgIsCutSize = false;
        if( in_array($ext, ['jpg','png','jpeg','bmp']) && $imgIsCutSize){
            $imgCutRatio = $request->input('imgCutRatio',env('IMG_CUT_RATION',700));//压缩比
            Log::info('开始压缩文件');
            $rs = Image::make($file->getRealPath())
                ->resize($imgCutRatio, $imgCutRatio, function ($constraint) {
                    $constraint->aspectRatio();
                })->save($absDir."/$fileName");
            if($rs === false){
                return responseFail('图片压缩失败');
            }
            Log::info('压缩完成');
            $filePath = "$middlePath/$fileName";
        }else{
            $filePath = $file->storeAs($middlePath,$fileName,'upload');
        }
        $filePath = '/storage/upload/'.$filePath;
        $imgUrl = asset($filePath);
        try{

            //Log::info('imgUrl',compact('imgUrl'));

            //$imgUrl = "https://bjyoupei.techbz.cn/storage/upload/order/4.jpg";
            //$imgUrl = "https://bjyoupei.techbz.cn/storage/upload/order/2.pdf";
            $texts = $this->tencentSDK($imgUrl);
            Log::info('text',$texts);
            $res = $this->handleText($texts);
            $res['img_url'] = $filePath;
            $res['is_show_car_jia_number'] = false;
            //$res['status'] = true;
            //return Response::json($res, 200, array('Content-Type' => 'application/json;charset=utf8'), JSON_UNESCAPED_UNICODE);
            //return response()->json($res,200,array('Content-Type' => 'application/json;charset=utf-8'),JSON_UNESCAPED_UNICODE);

            /*if(Str::contains($res['car_number'], '新车') || empty($res['car_number'])){
                $res['is_show_car_jia_number'] = true;
            }

            if(empty($res['car_jia_number']) && empty($res['car_number'])){
                $res['is_show_car_jia_number'] = false;
            }*/
            /**
             * 2023-04-04
             * 这块先恒改成false,识别了车牌号，前端那个标题就显示车牌号，识别了车架号，前端标题就是车架号，都没识别就显示
             * 车牌号/车架号,但是都没识别时，就等待用户自己输入，但是前端就一个输入框，车牌号车架号是两个字段，不能确定用户输入的是车牌号还是车架号，
             * ，所以恒返回false，让前端恒显示 车牌号/车架号
             */
            $res['is_show_car_jia_number'] = false;
            Log::info('res',$res);
            return responseSuccess($res);
        }catch(\Exception $e){
            $tip = $e->getFile().':'.$e->getLine().':'.$e->getMessage();
            Log::error($tip);
            return responseFail('识别错误，请上传正确的定损单');
        }
    }

    protected function tencentSDK($imgUrl) {
        $cert = new Credential(env('TENCENT_SECRET_ID'), env('TENCENT_SECRET_KEY'));

        $httpProfile = new HttpProfile();
        $httpProfile->setEndpoint('ocr.tencentcloudapi.com');

        $clientProfile = new ClientProfile();
        $clientProfile->setHttpProfile($httpProfile);

        $tableOCRRequest = new RecognizeTableOCRRequest();
        $tableOCRRequest->setImageUrl($imgUrl);
        $tableOCRRequest->setIsPdf(true);
        $client = new OcrClient($cert,'ap-beijing',$clientProfile);
        $res = $client->RecognizeTableOCR($tableOCRRequest);
        $info = $res->getTableDetections();

        $temp = [];
        foreach ($info as $item) {
            $cells = $item->Cells;
            foreach ($cells as $cell) {
                if(!empty($cell->Text))$temp[] = $cell->Text;
            }
        }
        return $temp;
    }

    protected function handleText(array $texts){
        $bao_xian_name = '';//被保险人
        $case_number = '';//立案号
        $chu_xian_date = '';//出险时间
        $car_number = '';//车牌号
        $car_jia_number = '';//车架号
        $ding_sun_price = 0;//定损金额

        foreach ($texts as $k=>$text) {

            if(Str::contains($text, '被保险人')){

                if(!empty($bao_xian_name))continue;

                if (Str::endsWith($text, '被保险人:')){
                    $bao_xian_name = $texts[$k+1];
                } else if(Str::contains($text, ':') && !Str::contains($text, '章')){
                    $bao_xian_name = explode(':', $text)[1];
                } else {
                    $bao_xian_name = Str::after($text,'被保险人');
                }

            }
            else if(Str::contains($text, '立案号')){
                $case_number = Str::after($text, ':');
            }
            else if(Str::contains($text, '报案号')){
                $case_number = Str::between($text, '报案号:','承保机构');
            }
            else if(Str::contains($text, '事故编号')){
                $case_number = Str::after($text, ':');
            }
            else if(Str::endsWith($text, '出险日期:')){
                $chu_xian_date = $texts[$k+1];
            }
            else if(Str::contains($text, '出险时间')){
                $chu_xian_date = Str::after($text, ':');
            }
            else if(Str::endsWith($text, '车牌号:')){
                if(!empty($car_number))continue;
                $car_number =  $texts[$k+1];
            }
            else if(Str::contains($text, '号牌号码')){
                if(!empty($car_number))continue;
                $car_number =  Str::after($text, ':');
            }
            else if(Str::contains($text, '车牌号码')){
                if(!empty($car_number))continue;
                $len = Str::contains($text, '车牌号码:')?5:4;
                $car_number = mb_substr($text,mb_strpos($text, "号牌号码")+$len,-1,"UTF-8");
            }
            else if(Str::endsWith($text, '车架号:')){
                if(!empty($car_jia_number))continue;
                $car_jia_number = $texts[$k+1];
            }
            else if(Str::contains($text, '车架号码') || Str::contains($text, '车架号')){
                if(!empty($car_jia_number))continue;
                if( Str::contains($text, '(') && Str::contains($text, ')')){
                    $car_jia_number = Str::between(Str::after($text, ':'), '(', ')');
                }else{
                    $car_jia_number = Str::after($text, ':');
                }

            }
            else if(Str::contains($text, '维修费总金额《含税):')){
                $text = $texts[$k+1];
                $ding_sun_price = Arr::first(findNum($text));
            }
            else if(Str::contains($text, '总计金额')){
                $text = Str::replace(' ', '', $text);
                $temp = findFloatNum($text)[0];
                foreach ($temp as $item) {
                    if($item>0)$ding_sun_price = $item;
                }
            }
            else if(Str::contains($text, '定损金额总计')){
                $text = Str::after($text, '定损金额总计');
                $ding_sun_price = Arr::first(findNum($text));
            }

        }

        $chu_xian_date = date('Y-m-d H:i:s',strtotime($chu_xian_date));

        $info = compact('bao_xian_name','chu_xian_date','ding_sun_price','car_number','car_jia_number','case_number');
        foreach ($info as $k=>$v) {
            if(in_array($k, ['case_number','bao_xian_name','car_jia_number','car_number'])){
                $info[$k] = trim($info[$k]);
                $info[$k] = Str::replace(' ', '',$info[$k]);
            }elseif($k=='chu_xian_date'){
                $v = Str::replace('年', '-', $v);
                $v = Str::replace('月', '-', $v);
                $v = Str::replace('日', '', $v);
                $info[$k] = date('Y-m-d H:i:s',strtotime($v));
            }else{
                $v = Str::replace(' ', '', $v);
                //$info[$k] = trim($v);
            }

        }
        Log::info('ocr',$info);
        $info['ding_sun_price'] = $info['ding_sun_price']??0;
        $ocr = Ocr::create($info);
        $info['ocr_id'] = $ocr->id;
        return $info;

    }

    public function apply(Request $request) {
        Log::info('apply',$request->input());
        $token = $request->header('token');
        $id = checkJWT($token)['id'];
        $user = User::where(compact('id'))->first();
        if(empty($user))
            return responseFail('未找到有效用户');
        $user_id = $user->id;
        $order_id = $request->input('id');
        $ocr_id = $request->input('ocr_id');

        $bao_xian_name = $request->input('bao_xian_name');
        $chu_xian_date = $request->input('chu_xian_date');
        $ding_sun_price = $real_ding_sun_price = $request->input('ding_sun_price');
        $car_number = $request->input('car_number');
        Log::info('car_number:'.$car_number );
        $car_jia_number = $request->input('car_jia_number');
        Log::info('car_jia_number:'.$car_jia_number );

        //如果没有识别出来车牌号和车架号，用户就自己输入，这样前段会把默认的输入给车架号，但是用户一般会输入的是车牌号，
        //所以当$orc->car_number&&$orc->car_jia_number 都是空的（说明识别的车牌号/车架号都是空的），然后用户自己
        //输入的car_jia_number不为空且length($car_jia_number)<14，说明用户输入的是车牌号
        $orc = Ocr::where('id',$ocr_id)->first();
        if( (empty($orc->car_number) && empty($orc->car_jia_number)) &&
            !empty($car_jia_number) && Str::length($car_jia_number)<14){
            $car_number = $car_jia_number;
            $car_jia_number = '';
        }

        $case_number = $request->input('case_number');

        $ding_sun_url = $request->input('ding_sun_url');
        $cancel_case_url = $request->input('cancel_case_url');
        $img_urls = $request->input('img_urls');
        $repaired_urls = $request->input('repaired_urls');

        $bank_type = $request->input('bank_type');
        $bank_account_name = $request->input('bank_account_name');
        $bank_card = $request->input('bank_card');

        $this->validate($request, [
            'bao_xian_name'=>'required',
            //'chu_xian_date'=>'required|date_format:Y-m-d H:i:s',
            //'chu_xian_date'=>'required',
            'ding_sun_price'=>'required|numeric|gt:0',
            //'car_number'=>'required',
            //'car_jia_number'=>'required',
            //'case_number'=>'required',
            'ding_sun_url'=>'required',
            'cancel_case_url'=>'required',
            'img_urls'=>'required',
            'repaired_urls'=>'required',
            'bank_account_name'=>'required',
            'bank_type'=>'required',
            'bank_card'=>'required',
            'ocr_id'=>'required',
        ],[],[
            'bao_xian_name'=>'保险人姓名',
            'chu_xian_date'=>'出险日期',
            'ding_sun_price'=>'定损金额',
            'car_number'=>'车牌号',
            'car_jia_number'=>'车架号',
            'case_number'=>'立案号',
            'ding_sun_url'=>'定损单图片',
            'repaired_urls'=>'修复后照片',
            'cancel_case_url'=>'销案证明',
            'img_urls'=>'车部损失照片',
            'bank_account_name'=>'收款户名',
            'bank_type'=>'收款银行',
            'bank_card'=>'收款账号',
        ]);


        //没有车牌号或者是新车，就用车架号
        if(Str::contains($car_number, '新车') || empty($car_number)){
            if(ChengBao::where(['beibao_name'=>$bao_xian_name,'car_jia_number'=>$car_jia_number])->count()<=0)
                return responseFail('该车辆不在承保范围内。');
            if(empty($user->car_jia_number))
                return responseFail('未查到当前用户的车架号！');
            //当前用户的承保单
            $chengBaoOfCurrentUser = ChengBao::where(['car_jia_number'=>$user->car_jia_number])->first();
        }else{
            if(ChengBao::where(['beibao_name'=>$bao_xian_name,'car_number'=>$car_number])->count()<=0)
                return responseFail('该车辆不在承保范围内。');
            if(empty($user->car_number))
                return responseFail('未查到当前用户的车牌号！');
            //当前用户的承保单
            $chengBaoOfCurrentUser = ChengBao::where(['car_number'=>$user->car_number])->first();
        }
        if(empty($chengBaoOfCurrentUser) || $chengBaoOfCurrentUser->beibao_name!=$bao_xian_name)
            //return responseFail('该申请车辆不属于注册车辆的被保险人，请确认后重新申请。');
        if(empty($chengBaoOfCurrentUser) || $chengBaoOfCurrentUser->beibao_name!=$bank_account_name)
            //return responseFail('收款户名请输入被保险人姓名！');



        //如果定损金额大于max_ding_sun_price，则实际赔付max_ding_sun_price
        $max_ding_sun_price_record = SysSetting::where('key','max_ding_sun_price')->first();
        $max_ding_sun_price = empty($max_ding_sun_price_record)?600:$max_ding_sun_price_record->val;
        if($ding_sun_price>$max_ding_sun_price)$real_ding_sun_price=$max_ding_sun_price;


        //$status = OrderConstant::STATUS_WAIT_AUTO_CHECK;
        $status = OrderConstant::STATUS_WAIT_HUMAN_CHECK;
        $reason = null;
        $info = compact('bao_xian_name','chu_xian_date','ding_sun_price','car_number','case_number','real_ding_sun_price',
            'ding_sun_url','cancel_case_url','img_urls', 'car_jia_number','user_id','status','reason','ocr_id','bank_account_name',
            'bank_card','bank_type','repaired_urls');
        try{
            DB::beginTransaction();
            Log::info('info',$info);
            $order = Order::updateOrCreate(['id'=>$order_id],$info);

            //与ocr数据对比
            $order->compareOcr();

            //Log::info('order',compact('order'));
            //Artisan::call('check:auto',['id'=>$order->id]);
            DB::commit();
            return responseSuccess();
        }catch(\Exception $e){
            DB::rollBack();
            $tip = $e->getFile().':'.$e->getLine().':'.$e->getMessage();
            Log::error($tip);
            return responseFail($tip);
        }
    }

    public function index(Request $request) {

        $token = $request->header('token');
        $userId = checkJWT($token)['id'];

        $page = $request->input('page',1);
        $page_size = $request->input('page_size',20);

        $status = $request->input('status',OrderConstant::STATUS_WAIT_AUTO_CHECK);
        if($status==OrderConstant::STATUS_WAIT_AUTO_CHECK){
            $status = [OrderConstant::STATUS_WAIT_AUTO_CHECK,OrderConstant::STATUS_WAIT_HUMAN_CHECK,OrderConstant::STATUS_WAIT_AUTO_HUMAN_CHECK];
        }
        $conditions = compact('userId','status');
        $this->getCol = ['id','created_at','case_number','car_number','status','reason'];
        $order = new Order();
        $records = $order->getLst($conditions)->paginate($page_size,$this->getCol,'page',$page);

        foreach ($records as $record) {
            $record->status_name = OrderConstant::MAP_STATUS[$record->status]??'未知';
            if(!empty($record->car_number)){
                $record->number = '车牌号:'.$record->car_number;
            }else{
                $record->number = '车架号:'.$record->car_jia_number;
            }
        }

        $countWaitCheck = $order->getLst(['status'=>[OrderConstant::STATUS_WAIT_AUTO_CHECK,OrderConstant::STATUS_WAIT_HUMAN_CHECK,OrderConstant::STATUS_WAIT_AUTO_HUMAN_CHECK],'userId'=>$userId])->count(['id']);
        $countCheckPass = $order->getLst(['status'=>OrderConstant::STATUS_CHECK_PASS,'userId'=>$userId])->count(['id']);
        $countCancel = $order->getLst(['status'=>OrderConstant::STATUS_CANCEL,'userId'=>$userId])->count(['id']);
        $countCheckNotPass = $order->getLst(['status'=>OrderConstant::STATUS_CHECK_NOT_PASS,'userId'=>$userId])->count(['id']);

        $mapStatus = OrderConstant::MAP_STATUS;

        return responseSuccess($records->items(),$records->total(),100000,compact('countWaitCheck','countCheckPass','countCheckNotPass','countCancel','mapStatus'));
    }


    /**
     * 自主维修 - 提交
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Validation\ValidationException
     */
    public function selfRepair(Request $request) {
        $id = $request->input('order_id');
        $repair_list_img_url = $request->input('repair_list_img_url');
        $bank_type = $request->input('bank_type');
        $bank_account_name = $request->input('bank_account_name');
        $bank_card = $request->input('bank_card');
        $invoice_url = $request->input('invoice_url');

        $this->validate($request, [
            'order_id'=>'required|Integer',
            'repair_list_img_url'=>'required',
            'bank_type'=>'required',
            'bank_card'=>'required',
        ],[],[
            'order_id'=>'订单编号',
            'repair_list_img_url'=>'维修清单',
            'bank_account_name'=>'开户姓名',
            'bank_type'=>'开户行',
            'bank_card'=>'银行卡',
        ]);
        $status = OrderConstant::STATUS_WAIT_OFF;
        Order::where(compact('id'))->update(compact('repair_list_img_url','bank_card','bank_type','invoice_url','status','bank_account_name'));
        return responseSuccess();
    }

    public function sendInvoiceAddress(Request $request) {

        $address = SysSetting::where('key','like','revice_%')->get(['key','val']);
        return responseSuccess($address->toArray());

    }

    public function searchRepairFactoryLst_chunk(Request $request) {

        $lat = $request->input('lat');
        $lng = $request->input('lng');

        $this->validate($request, [
            'lat'=>'required',
            'lng'=>'required',
        ],[],[
            'lat'=>'经度',
            'lng'=>'纬度',
        ]);

        $key = "DDJBZ-W6XW6-3VESU-EYQWU-4XZH7-OIFI7";
        $url = "https://apis.map.qq.com/ws/geocoder/v1/?key=$key&location=$lat,$lng";

        $location = json_decode(makeRequest($url)['result'],true);

        $city = $location['result']['address_component']['city'];

        Log::info('searchRepairFactoryLst',compact('city','lat','lng'));
        $cityCode = China::where('name','like',"%$city%")->first()->code;
        $factories = [];
        //['id','name','address','business_s_time','business_e_time','lat','lng','imgs']
        RepairFactory::where('city_code',$cityCode)
            ->where('status',1)
            ->chunk(5,function ($records) use ($lat,$lng,$key,$factories){
                $points = [];
                foreach ($records as $record) {
                    $points[] = $record->lat.",".$record->lng;
                }
                $from = $lat.",".$lng;
                $to = implode(';', $points);
                $mode = "driving";
                $url = "https://apis.map.qq.com/ws/distance/v1/matrix?key=$key&from=$from&to=$to&mode=$mode";
                $res = makeRequest($url);
                Log::info('url:'.$url);
                Log::info('res:',$res);
                $distanceInfo = json_decode($res['result'],true)['result']['rows'][0]['elements'];
                foreach ($records as $k=>$record) {
                    $record->distance = ($distanceInfo[$k]['distance']/1000);
                    $record->business_time = $record->business_s_time.' - '. $record->business_e_time;
                    $record->cover_url = Arr::first(explode(',', $record->imgs));
                }
                $factories = array_merge($factories,$records->toArray());
                Log::info('factories',$factories);
            });
        array_multisort($distance, SORT_ASC, $factories);
        foreach ($factories as $record) {
            $record['distance'] .= 'km';
        }

        return responseSuccess($factories,count($factories));
    }
    public function searchRepairFactoryLst(Request $request) {

        $lat = $request->input('lat');
        $lng = $request->input('lng');

        $this->validate($request, [
            'lat'=>'required',
            'lng'=>'required',
        ],[],[
            'lat'=>'经度',
            'lng'=>'纬度',
        ]);

        if(env('app_env')=='local'){
            $city = "临沂";
        }else{
            $key = "DDJBZ-W6XW6-3VESU-EYQWU-4XZH7-OIFI7";
            $url = "https://apis.map.qq.com/ws/geocoder/v1/?key=$key&location=$lat,$lng";
            $location = json_decode(makeRequest($url)['result'],true);
            $city = $location['result']['address_component']['city'];
        }
        Log::info('searchRepairFactoryLst',compact('city','lat','lng'));
        $cityCode = China::where('name','like',"%$city%")->first()->code;

        $records = RepairFactory::where('city_code',$cityCode)
            ->where('status',1)
            ->get(['id','name','address','business_s_time','business_e_time','lat','lng','imgs']);
        $points = [];
        foreach ($records as $record) {
            $points[] = $record->lat.",".$record->lng;
        }

        $from = $lat.",".$lng;
        $to = implode(';', $points);
        $mode = "driving";
        $url = "https://apis.map.qq.com/ws/distance/v1/matrix?key=$key&from=$from&to=$to&mode=$mode";
        Log::info('url:'.$url);
        $res = makeRequest($url);
        Log::info('res:',$res);

        $distanceInfo = json_decode($res['result'],true)['result']['rows'][0]['elements'];

        foreach ($records as $k=>$record) {
            $record->distance = ($distanceInfo[$k]['distance']/1000);
            $record->business_time = $record->business_s_time.' - '. $record->business_e_time;
            $record->cover_url = Arr::first(explode(',', $record->imgs));
            $record->star = $record->getStar();
        }

        $factories = $records->toArray();
        array_multisort(array_column($factories, 'distance'),SORT_ASC,$factories);

        //$records = $records->sortBy('distance');
        //$records->values()->all();
        foreach ($factories as &$factory) {
            $factory['distance'] .= 'km';
        }

        return responseSuccess($factories,count($factories));
    }

    public function appointRepairFactory(Request $request) {
        $id = $request->input('order_id');
        $repair_factory_id = $request->input('repair_factory_id');

        $this->validate($request, [
            'order_id'=>'required|Integer',
            'repair_factory_id'=>'required|Integer'
        ],[]);

        $order = Order::where(compact('id'))->first();
        $order->repair_factory_id = $repair_factory_id;
        $order->status = OrderConstant::STATUS_WAIT_RECEIVING;
        $order->save();


        $phones = RepairFactoryAdmin::where(['factory_id'=>$repair_factory_id])->pluck('phone')->toArray();
        foreach ($phones as $phone) {
            //TODO 发送短信通知给 修理厂管理员
        }


        return responseSuccess();
    }
}
